<?php

	namespace org\tekuna\base\classloader;

	use org\tekuna\base\classloader\ClassLoadException;


	/**
	 * The PharClassLoader is a ClassLoader implementation that loads classes
	 * out of a directory structure that resides inside a PHP archive (PHAR). The 
	 * directories must be organized like the class namespaces. Classes must 
	 * have the filename ClassName.class.php and Interfaces InterfaceName.interface.php
	 * 
	 * Class: foo\bar\Baz
	 * File: foo/bar/Baz.class.php
	 * 
	 * Interface: this\is\the\Interface
	 * File: this/is/the/Interface.interface.php
	 */
	class PharClassLoader extends AbstractClassLoader {
	
		private
			$sPharPath = NULL, 
			$sBaseDir = NULL;
	
	
		/**
		 * Construct a new PharClassLoader with the PHAR where the classes are stored
		 * and a certain base directory inside this PHAR. The default value is 'src' 
		 * for the base directory. Throws a ClassLoadException if the PHAR does not exist.
		 * 
		 * @param String $sPharPath the path to the PHAR
		 * @param String $sBaseDir the base directory inside the PHAR
		 */
		public function __construct($sPharPath, $sBaseDir = 'src') {
			
			if (! is_file($sPharPath)) {
				
				throw new ClassLoadException("The PHP archive '$sPharPath' does not exist.");
			}

			$this -> sPharPath = $sPharPath;
			$this -> sBaseDir = $sBaseDir;
		}
	
	
		/**
		 * Load the specified class from the given namespace. 
		 * 
		 * @param String $sNamespace the namespace
		 * @param String $sClassName the name of the class
		 */
		public function loadClass($sNamespace, $sClassName) {
	
			// the directory inside the phar
			$sPharPath = 'phar://'. $this -> sPharPath . DS;
			$sClassDirectory = $this -> sBaseDir . DS . str_replace('\\', DS, $sNamespace) . DS;

			// try to load a class
			$sClassPath = $sPharPath . $sClassDirectory . $sClassName . '.class.php';
			if (file_exists($sClassPath)) {
				
				require $sClassPath;
				return;
			}
			
			// try to load an interface
			$sInterfacePath = $sPharPath . $sClassDirectory . $sClassName . '.interface.php';
			if (file_exists($sInterfacePath)) {
				
				require $sInterfacePath;
			}
		}
		

		/**
		 * Returns a string representation of this class loader including the 
		 * PHAR path and the base directory parameter
		 * 
		 * @return String this class loader's string representation
		 */
		public function __toString() {

			return __CLASS__ .' [phar = '. $this -> sPharPath .'; base directory = '. $this -> sBaseDir .']';			
		}
	}
